package jsr166.contrib.uncontended;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

/**
 * This class decorates a Lock, modifying it only by
 * adding a slight delay after the lock is released. This may be useful
 * if you think the code is correctly synchronized 
 * but may suffer from atomicity problems.
 * @author pugh
 *
 */
public class SlowReleasingLock implements Lock {

    final Lock lock;
    final long delay;
    /**
     * This lock will delay for one millisecond after releasing the lock.
     *
     */
    public SlowReleasingLock(Lock lock) {
        this.lock = lock;
        delay = 1L;
    }
    /**
     * This lock will delay the specified time after releasing the lock.
     *
     */
    public SlowReleasingLock(Lock lock, long time, TimeUnit unit) {
        if (lock == null) throw new NullPointerException("lock parameter must not be null");
        this.lock = lock;
        this.delay = unit.toMillis(time);
    }
    private static final long serialVersionUID = 1L;
    

    public void unlock() {
        lock.unlock();
        try {
            Thread.sleep(delay);
        } catch (InterruptedException e) {
            try {
            Thread.currentThread().interrupt();
            } catch (SecurityException e2) {
                assert true; // nothing to do, interrupt will be lost
            }
        }
        
    }
    public void lock() {
        lock.lock();
        
    }
    public void lockInterruptibly() throws InterruptedException {
      lock.lockInterruptibly();
        
    }
    public Condition newCondition() {
       return lock.newCondition();
    }
    public boolean tryLock() {
       return lock.tryLock();
    }
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
       return lock.tryLock(time, unit);
    }
}
